package pers.wang.toolset.httpclient.spring.boot.autoconfigure;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

import pers.wang.toolset.httpclient.spring.boot.autoconfigure.condition.BasicHttpClientCondition;

@Conditional(BasicHttpClientCondition.class)
@Configuration
@ConfigurationProperties(prefix = "toolset.http")
public class HttpClientConfigure {
	/**
	 * 连接超时时间
	 */
	private int connectionTimeOut = 10000;
	/**
	 * 读取超时时间
	 */
	private int socketTimeOut = 10000;
	/**
	 * 最大连接数
	 */
	private int maxTotal = 2000;
	/**
	 * 默认的每个路由的最大连接数
	 */
	private int defaultMaxPerRoute = 200;
	/**
	 * 设置到某个路由的最大连接数，会覆盖defaultMaxPerRoute
	 */
	private int maxPerRoute = 200;

	@Bean
	public CloseableHttpClient basicHttpClient() {
		// 连接管理器，使用无惨构造
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
		// 最大连接数
		connManager.setMaxTotal(maxTotal);
		// 默认的每个路由的最大连接数
		connManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
		//socket配置（默认配置和某个host的配置）
		SocketConfig socketConfig = SocketConfig.custom()
				.setTcpNoDelay(true)     //是否立即发送数据，设置为true会关闭Socket缓冲，默认为false
				.setSoReuseAddress(true) //是否可以在一个进程关闭Socket后，即使它还没有释放端口，其它进程还可以立即重用端口
				.setSoTimeout(500)       //接收数据的等待超时时间，单位ms
				.setSoLinger(60)         //关闭Socket时，要么发送完所有数据，要么等待60s后，就关闭连接，此时socket.close()是阻塞的
	            .setSoKeepAlive(true)    //开启监视TCP连接是否有效
	            .build();
		connManager.setDefaultSocketConfig(socketConfig);
		
		//request请求相关配置
		RequestConfig defaultRequestConfig = RequestConfig.custom()
				.setConnectTimeout(connectionTimeOut)         //连接超时时间
                .setSocketTimeout(socketTimeOut)          //读超时时间（等待数据超时时间）
                .setConnectionRequestTimeout(500)    //从池中获取连接超时时间
                .build();
		CloseableHttpClient httpclient = HttpClients.custom()
	            .setConnectionManager(connManager)             //连接管理器
	            .setDefaultRequestConfig(defaultRequestConfig) //默认请求配置
	            .build();
		return httpclient;
	}

	public int getConnectionTimeOut() {
		return connectionTimeOut;
	}

	public void setConnectionTimeOut(int connectionTimeOut) {
		this.connectionTimeOut = connectionTimeOut;
	}

	public int getSocketTimeOut() {
		return socketTimeOut;
	}

	public void setSocketTimeOut(int socketTimeOut) {
		this.socketTimeOut = socketTimeOut;
	}

	public int getMaxTotal() {
		return maxTotal;
	}

	public void setMaxTotal(int maxTotal) {
		this.maxTotal = maxTotal;
	}

	public int getDefaultMaxPerRoute() {
		return defaultMaxPerRoute;
	}

	public void setDefaultMaxPerRoute(int defaultMaxPerRoute) {
		this.defaultMaxPerRoute = defaultMaxPerRoute;
	}

	public int getMaxPerRoute() {
		return maxPerRoute;
	}

	public void setMaxPerRoute(int maxPerRoute) {
		this.maxPerRoute = maxPerRoute;
	}
}
